/**
 * autoQuery 自动查询构建器示例和最佳实践
 * 提供完整的使用示例和各种查询场景演示
 * @author sun
 * @date 2024-03-30
 * @update 2024-07-13
 */

// 直接从各自的文件中导入，避免潜在的循环依赖问题
import { QueryBuilder } from './QueryBuilder';
import { QueryTools } from './tools';
import { QueryOperator } from './types';
import { Condition, AndGroup, OrGroup, Range } from './decorators';

/**
 * 打印分隔线
 * @param title 标题
 */
function printSeparator(title: string) {
  const separator = '='.repeat(20);
  console.log(`\n${separator} ${title} ${separator}`);
}

/**
 * 打印查询条件
 * @param title 标题
 * @param condition 查询条件
 */
function printCondition(title: string, condition: any) {
  console.log(`\n▶ ${title}:`);
  console.log(JSON.stringify(condition, null, 2));
}

// 模拟表格服务
const mockTableService = {
  query: (page: number, size: number, condition: any[]) => {
    printCondition('执行查询', condition);
    return Promise.resolve({
      data: [],
      total: 0,
      page,
      size,
    });
  },
};

/**
 * 产品类型定义
 */
interface Product {
  id: string;
  name: string;
  price: number;
  type: string;
  brand: string;
  createTime: Date;
  status: number;
}

/**
 * 一、装饰器方式
 * 使用装饰器标记类属性作为查询条件
 */

// 品牌条件类
class BrandCondition {
  @Condition(QueryOperator.EQUAL, null)
  brand?: string;

  constructor(brand?: string) {
    this.brand = brand;
  }
}

// 产品查询条件类
class ProductQuery {
  // 1. 基本条件
  @Condition(QueryOperator.LIKE, null)
  name?: string;

  @Condition(QueryOperator.EQUAL, null)
  type?: string;

  // 2. 范围条件
  @Range('price')
  priceRange?: [number, number];

  // 3. 日期范围
  @Range('createTime')
  createTimeRange?: [Date, Date];

  // 4. 嵌套OR条件组
  @OrGroup()
  brands?: BrandCondition[];

  // 5. 状态IN条件
  @Condition(QueryOperator.IN, null)
  status?: number[];

  constructor(init?: Partial<ProductQuery>) {
    if (init) {
      Object.assign(this, init);
    }
  }
}

/**
 * 简单用户查询条件类
 */
class UserSearchForm {
  @Condition(QueryOperator.LIKE)
  name?: string;

  @Condition(QueryOperator.EQUAL)
  status?: number;

  @Range('age')
  ageRange?: [number, number];

  @Condition(QueryOperator.IN)
  roles?: string[];

  @Range('registrationTime')
  dateRange?: [Date, Date];

  constructor(init?: Partial<UserSearchForm>) {
    if (init) {
      Object.assign(this, init);
    }
  }
}

/**
 * 使用装饰器方式构建查询条件 - 产品示例
 * 优点: 代码结构清晰，类型安全
 * 适合: 结构化查询，复杂表单
 */
export function exampleUsingDecorators() {
  printSeparator('装饰器方式 - 产品示例');

  // 创建查询条件实例
  const query = new ProductQuery({
    name: '笔记本', // LIKE条件 - 将自动添加 %% 进行全模糊匹配
    type: '电子产品', // 等值条件
    priceRange: [5000, 10000], // 范围条件
    brands: [
      // OR条件组
      new BrandCondition('苹果'),
      new BrandCondition('联想'),
    ],
    status: [1, 2, 3], // IN条件
  });

  // 从装饰器构建查询条件
  const condition = QueryBuilder.fromDecorators(query);
  printCondition('产品查询条件', condition);

  return condition;
}

/**
 * 使用装饰器方式构建查询条件 - 用户示例
 */
export function exampleUsingUserDecorators() {
  printSeparator('装饰器方式 - 用户示例');

  // 创建查询实例
  const searchForm = new UserSearchForm({
    name: '张%', // 模糊匹配
    status: 1, // 活跃状态
    ageRange: [18, 30], // 年龄范围
    roles: ['admin', 'editor'], // 角色列表
    dateRange: [new Date('2023-01-01'), new Date('2023-12-31')], // 日期范围
  });

  // 生成查询条件
  const condition = QueryBuilder.fromDecorators(searchForm);
  printCondition('用户查询条件', condition);

  // 执行查询
  return mockTableService.query(1, 10, condition);
}

/**
 * 二、链式API方式
 * 使用链式方法调用构建查询条件
 * 优点: 直观，不依赖装饰器
 * 适合: 动态构建条件
 */
export function exampleUsingChainedAPI() {
  printSeparator('链式API方式');

  // 创建查询构建器实例
  const condition = QueryBuilder.create()
    .like('name', '笔记本') // 全模糊匹配（自动添加%%）
    .startsWith('code', 'A') // 开头匹配（自动添加A%）
    .endsWith('category', '电器') // 结尾匹配（自动添加%电器）
    .equal('type', '电子产品')
    .beginAndGroup()
    .greaterThanOrEqual('price', 5000)
    .lessThanOrEqual('price', 10000)
    .endGroup()
    .beginOrGroup()
    .equal('brand', '苹果')
    .equal('brand', '联想')
    .endGroup()
    .in('status', [1, 2, 3])
    .build();

  printCondition('链式API生成的条件', condition);

  return condition;
}

/**
 * 三、对象表达式方式
 * 使用MongoDB风格的对象表达式构建查询条件
 * 优点: 简洁，易序列化
 * 适合: 配置驱动的查询
 */
export function exampleUsingObjectExpression() {
  printSeparator('对象表达式方式');

  // 创建查询对象
  const queryObject = {
    name: { $like: '笔记本' }, // 全模糊匹配（自动添加%%）
    code: { $startsWith: 'A' }, // 开头匹配（自动添加A%）
    category: { $endsWith: '电器' }, // 结尾匹配（自动添加%电器）
    type: { $eq: '电子产品' },
    price: {
      $gte: 5000,
      $lte: 10000,
    },
    $or: [{ brand: { $eq: '苹果' } }, { brand: { $eq: '联想' } }],
    status: { $in: [1, 2, 3] },
  };

  // 从对象构建查询条件
  const condition = QueryBuilder.fromObject(queryObject);
  printCondition('对象表达式生成的条件', condition);

  return condition;
}

/**
 * 四、工具函数方式
 * 使用QueryTools工具函数构建查询条件
 * 优点: 简洁，空值处理
 * 适合: 函数式风格
 */
export function exampleUsingToolFunctions() {
  printSeparator('工具函数方式');

  // 使用工具函数构建查询条件
  const condition = QueryTools.and(
    QueryTools.like('name', '笔记本'), // 全模糊匹配（自动添加%%）
    QueryTools.startsWith('code', 'A'), // 开头匹配（自动添加A%）
    QueryTools.endsWith('category', '电器'), // 结尾匹配（自动添加%电器）
    QueryTools.equal('type', '2'),
    QueryTools.range('price', 5000, 10000),
    QueryTools.or(QueryTools.equal('brand', '苹果'), QueryTools.equal('brand', '联想')),
    QueryTools.in('status', [1, 2, 3]),
  );

  printCondition('工具函数生成的条件', condition);

  return condition;
}

/**
 * 五、空值处理示例
 * 展示空值如何被自动处理
 */
export function exampleNullValueHandling() {
  printSeparator('空值处理示例');

  // 包含空值的查询参数
  const searchParams = {
    name: '', // 空字符串
    status: null, // null值
    ageRange: [18, null], // 部分为null的数组
    roles: [], // 空数组
  };

  // 使用QueryTools构建条件（会自动处理空值）
  const condition = QueryTools.and(
    QueryTools.like('name', searchParams.name), // 会被忽略
    QueryTools.equal('status', searchParams.status), // 会被忽略
    QueryTools.in('role', searchParams.roles), // 会被忽略
    QueryTools.range('age', searchParams.ageRange[0], searchParams.ageRange[1]), // 只会生成 age >= 18
  );

  printCondition('空值处理结果 (QueryTools)', condition);

  // 或者使用链式API
  const builderCondition = new QueryBuilder()
    .like('name', searchParams.name) // 会被忽略
    .equal('status', searchParams.status) // 会被忽略
    .in('role', searchParams.roles) // 会被忽略
    .greaterThanOrEqual('age', searchParams.ageRange[0]) // 会被添加
    .lessThanOrEqual('age', searchParams.ageRange[1]) // 会被忽略
    .build();

  printCondition('空值处理结果 (链式API)', builderCondition);

  return { condition, builderCondition };
}

/**
 * 六、复杂嵌套条件示例
 * 展示构建含有多层嵌套的复杂查询条件
 */
export function exampleComplexNestedCondition() {
  printSeparator('复杂嵌套条件示例');

  // 构建复杂嵌套条件
  const condition = QueryTools.and(
    // 基础条件
    QueryTools.equal('type', '电子产品'),

    // 产品名称模糊匹配示例，展示三种模式
    QueryTools.or(
      QueryTools.like('name', '笔记本'), // 全模糊：%笔记本%
      QueryTools.startsWith('name', '平板'), // 开头匹配：平板%
      QueryTools.endsWith('name', '手机'), // 结尾匹配：%手机
    ),

    // 价格在5000-10000或者状态为特价的高端产品
    QueryTools.or(
      // 价格区间
      QueryTools.range('price', 5000, 10000),

      // 特价高端产品
      QueryTools.and(
        QueryTools.equal('status', 4), // 特价状态
        QueryTools.greaterThan('price', 10000), // 高端产品
      ),
    ),

    // 品牌条件
    QueryTools.or(
      QueryTools.equal('brand', '苹果'),
      QueryTools.equal('brand', '华为'),
      QueryTools.equal('brand', '三星'),
    ),
  );

  printCondition('复杂嵌套条件', condition);

  return condition;
}

/**
 * 七、与实际表单集成示例
 * 将表单数据转换为查询条件
 */
export function exampleFormIntegration(formValues?: any) {
  printSeparator('表单集成示例');

  // 模拟从表单获取的值
  const formData = formValues || {
    keyword: '测试',
    status: 1,
    dateRange: ['2023-01-01', '2023-12-31'],
    categories: ['A', 'B'],
    price: [100, 500],
    isAvailable: true,
  };

  // 构建查询条件
  const condition = QueryTools.and(
    // 关键字搜索 - 同时匹配多个字段
    formData.keyword
      ? QueryTools.or(
          QueryTools.like('name', formData.keyword),
          QueryTools.like('description', formData.keyword),
        )
      : [],

    // 状态条件
    QueryTools.equal('status', formData.status),

    // 日期范围
    formData.dateRange?.length === 2
      ? QueryTools.between(
          'createdAt',
          new Date(formData.dateRange[0]),
          new Date(formData.dateRange[1]),
        )
      : [],

    // 分类条件
    formData.categories?.length > 0 ? QueryTools.in('category', formData.categories) : [],

    // 价格范围
    QueryTools.range('price', formData.price?.[0], formData.price?.[1]),

    // 布尔值条件
    QueryTools.equal('isAvailable', formData.isAvailable),
  );

  printCondition('表单集成生成的条件', condition);

  return mockTableService.query(1, 10, condition);
}

/**
 * 八、生成实际应用格式
 * 展示生成的条件与实际使用的格式对比
 */
export function exampleRequestedFormat() {
  printSeparator('实际格式示例');

  // 示例1: ["in", "cmpt_state", [0, 1, 2, 3, 4, 6]]
  const condition1 = QueryTools.in('cmpt_state', [0, 1, 2, 3, 4, 6]);

  // 示例2: ["and", ["in","id",["1001","1002","1003"]], ["=","is_deleted",0]]
  const condition2 = QueryTools.and(
    QueryTools.in('id', ['1001', '1002', '1003']),
    QueryTools.equal('is_deleted', 0),
  );

  // 空值示例: 不生成无效条件
  const nullExample = QueryTools.equal('status', null);

  printCondition('示例1 - in条件', condition1);
  printCondition('示例2 - and条件', condition2);
  printCondition('空值示例', nullExample);

  return { condition1, condition2, nullExample };
}

/**
 * 九、模糊查询方法示例
 * 展示包含匹配、开头匹配和结尾匹配的不同用法
 */
export function exampleLikeMethods() {
  printSeparator('模糊查询方法示例');

  // 1. 默认包含匹配模式 (like)
  const containsCondition = QueryTools.like('name', '张三');
  // 输出: ["like", "name", "%张三%"]

  // 2. 开头匹配模式 (startsWith)
  const startsWithCondition = QueryTools.startsWith('name', '张');
  // 输出: ["like", "name", "张%"]

  // 3. 结尾匹配模式 (endsWith)
  const endsWithCondition = QueryTools.endsWith('name', '三');
  // 输出: ["like", "name", "%三"]

  // 4. 已包含通配符的像 - 仍会添加额外的通配符
  const wildcardCondition = QueryTools.like('code', 'A%01');
  // 输出: ["like", "code", "%A%01%"]

  // 5. 等于操作 (equal) - 使用=操作符（推荐用于精确匹配）
  const equalCondition = QueryTools.equal('code', 'A001');
  // 输出: ["=", "code", "A001"]

  // 链式API方式
  const builder = new QueryBuilder();
  const builderCondition = builder
    .like('description', '商品') // 包含匹配
    .startsWith('code', 'A') // 开头匹配
    .endsWith('name', '器') // 结尾匹配
    .equal('id', 1001) // 等于匹配
    .build();

  printCondition('包含匹配 (like)', containsCondition);
  printCondition('开头匹配 (startsWith)', startsWithCondition);
  printCondition('结尾匹配 (endsWith)', endsWithCondition);
  printCondition('已包含通配符的像 - 仍会添加额外的通配符', wildcardCondition);
  printCondition('等于操作 (equal)', equalCondition);
  printCondition('链式API模糊查询', builderCondition);

  // 添加说明信息
  console.log('\n📝 说明: ');
  console.log('1. 所有 LIKE 匹配都会自动添加 %% 通配符，包括已经包含 % 的字符串');
  console.log("2. 如果需要精确匹配，请使用等于操作(equal)，使用'='操作符");
  console.log('3. 开头匹配使用 startsWith，结尾匹配使用 endsWith');

  return {
    containsCondition,
    startsWithCondition,
    endsWithCondition,
    wildcardCondition,
    equalCondition,
    builderCondition,
  };
}

/**
 * 十、Mongoose风格对象表达式的模糊查询示例
 * 展示 $like、$startsWith 和 $endsWith 操作符的用法
 */
export function exampleMongooseStyle() {
  printSeparator('Mongoose风格对象表达式');

  // 创建查询对象
  const queryObject = {
    // 1. 包含匹配（默认添加 %% 包裹）
    name: { $like: '张三' },

    // 2. 开头匹配
    code: { $startsWith: 'A' },

    // 3. 结尾匹配
    title: { $endsWith: '器' },

    // 4. 手动指定通配符的情况
    description: { $like: '%特殊%商品%' },

    // 5. 复合条件
    $or: [{ category: { $eq: '电子产品' } }, { tags: { $like: '热门' } }],
  };

  // 从对象构建查询条件
  const condition = QueryBuilder.fromObject(queryObject);
  printCondition('Mongoose风格对象表达式', condition);

  return condition;
}

/**
 * 十一、智能查询条件构建示例
 * 展示自动类型识别和智能条件生成
 */
export function exampleSmartQuery() {
  printSeparator('智能查询构建器');

  // 模拟搜索表单数据
  const searchData = {
    name: '笔记本', // 字符串 -> 自动使用LIKE
    price: [5000, 10000], // 两个数字元素数组 -> 自动识别为范围
    dateRange: ['2023-01-01', '2023-12-31'], // 日期字符串数组 -> 自动识别为日期范围
    brands: ['苹果', '华为', '小米'], // 多元素数组 -> 自动使用IN
    inStock: true, // 布尔值 -> 等于
    category: '电子产品', // 字符串 -> 自动使用LIKE
    tags: [], // 空数组 -> 自动忽略
    description: null, // null -> 自动忽略
    code: 'A*', // 带*的字符串 -> 自动识别为开头匹配
    rating: '*5', // 带*的字符串 -> 自动识别为结尾匹配
    keyword: '*热门*', // 两端带*的字符串 -> 自动识别为包含匹配
    // 数组内无效值处理示例
    mixedArray: [null, '有效值', undefined, ''], // 数组中的无效值会被过滤，只保留 ["有效值"]
    partialRange: [100, null], // 部分有效的范围 -> 转为 price >= 100
    singleItemArray: [null, '唯一值', undefined], // 过滤后只有一个元素 -> 使用等于条件

    // 日期处理示例
    singleDate: [null, '2023-01-15', undefined], // 单一日期 -> 转为日期等于条件
    reversedDateRange: ['2023-12-31', '2023-01-01'], // 自动调整顺序为正确的日期范围
    multipleDates: ['2023-01-15', '2023-02-15', '2023-03-15'], // 多个日期 -> 转为IN条件
    mixedDateFormats: [new Date('2023-01-01'), '2023-02-01'], // 混合日期格式 -> 自动识别并处理
  };

  // 使用默认选项的智能查询
  const defaultCondition = QueryTools.smartQuery(searchData);
  printCondition('默认选项的智能查询', defaultCondition);

  // 指定某些字段使用特定操作符
  const customOperatorsCondition = QueryTools.smartQuery(searchData, {
    fieldOperators: {
      name: { operator: QueryOperator.EQUAL }, // name字段使用等于而非模糊匹配
      category: {
        handler: (field, value) => QueryTools.in(field, [value + '-handler']), // 自定义处理
      },
    },
    autoLike: false, // 关闭字符串自动模糊匹配
  });
  printCondition('自定义操作符的智能查询', customOperatorsCondition);

  // 使用分组功能
  const groupedCondition = QueryTools.smartQuery(searchData, {
    groups: {
      // name和category字段放在一个OR组中
      or: [['name', 'category']],
      // price和inStock字段放在一个AND组中
      and: [['price', 'inStock']],
    },
    // 排除某些字段
    exclude: ['code', 'rating'],
  });
  printCondition('使用分组的智能查询', groupedCondition);

  // 处理嵌套对象和复杂条件
  const complexData = {
    basic: {
      status: 1,
      type: '电子产品',
    },
    advanced: {
      price: { $gte: 5000 },
      rating: { $gte: 4 },
    },
    $or: [{ brand: '苹果' }, { brand: '华为' }],
  };

  // 处理嵌套结构
  const complexCondition = QueryTools.and(
    // 处理基础条件
    QueryTools.smartQuery(complexData.basic),
    // 处理高级条件
    QueryTools.smartQuery(complexData.advanced),
    // 处理OR条件
    QueryTools.smartQuery({ $or: complexData.$or }),
  );
  printCondition('处理复杂嵌套结构', complexCondition);

  return {
    defaultCondition,
    customOperatorsCondition,
    groupedCondition,
    complexCondition,
  };
}

/**
 * 运行所有示例
 */
export function runAllExamples() {
  console.log('\n🔍 autoQuery 查询构建器示例');
  console.log('='.repeat(60));

  // 1. 装饰器方式
  exampleUsingDecorators();
  exampleUsingUserDecorators();

  // 2. 链式API方式
  exampleUsingChainedAPI();

  // 3. 对象表达式方式
  exampleUsingObjectExpression();

  // 4. 工具函数方式
  exampleUsingToolFunctions();

  // 5. 空值处理
  exampleNullValueHandling();

  // 6. 复杂嵌套条件
  exampleComplexNestedCondition();

  // 7. 表单集成
  exampleFormIntegration();

  // 8. 实际格式生成
  exampleRequestedFormat();

  // 9. 模糊查询方法
  exampleLikeMethods();

  // 10. Mongoose风格
  exampleMongooseStyle();

  // 11. 智能查询构建器
  exampleSmartQuery();

  console.log('\n✅ 所有示例运行完成');
  console.log('='.repeat(60));
}

// 导出默认函数
export default runAllExamples;
